package com.tz.cartelo.activity;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import com.tz.cartelo.R;
import com.tz.cartelo.constant.Api;
import com.tz.cartelo.constant.Key;
import com.tz.cartelo.model.DataParams;
import com.tz.common.util.JsonUtils;
import com.tz.common.util.LogUtil;
import com.tz.common.util.PreferencesUtils;
import com.tz.common.util.VolleyDataUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.util.Map;

/**
 * Add network data handler for base activity
 * Created by Chris on 16/7/19.
 */
public abstract class DataLoadActivity extends BaseActivity {

    private static final String TAG = "ServerApi_Activity";

    public static String toJson(Object src) {
        return JsonUtils.toJson(src);
    }

    public static <T> T fromJson(String json, Class<T> classOfT) {
        return JsonUtils.fromJson(json, classOfT);
    }

    public static <T> T fromJson(String json, Type typeOfT) {
        return JsonUtils.fromJson(json, typeOfT);
    }

    //Call this method in subclass
    protected void loadData(Api api, boolean showLoading) {
        if (showLoading)
            showProgressDialog();
        initParams(api, showLoading);
    }

    //Init parameters, override in subclass
    protected void initParams(DataParams params) {
    }

    // Http response handler, override in subclass
    protected void disposeResult(Api api, String response) {
    }

    private void initParams(Api api, boolean loadHint) {
        DataParams params = new DataParams(api, loadHint);
        initParams(params);
        loadData(params);
    }

    private void loadData(DataParams params) {
        try {
            volleyMethod(params);
        } catch (Exception e) {
            LogUtil.e(TAG, "loadData() exception: " + e.getMessage());
        }
    }

    private void volleyMethod(DataParams param) {
        switch (param.getApi().getHttpMethod()) {
            case GET:
                volleyGet(param);
                break;
            case POST:
                volleyString(param, Request.Method.POST);
                break;
            case POST_JSON:
                volleyJson(param, Request.Method.POST);
                break;
            default:
                break;
        }
/*
        int method = param.getApi().getHttpMethod() == HttpMethod.GET
                ? Request.Method.GET : Request.Method.POST;
        if (method == Request.Method.POST) {
            volleyString(param, method);
        } else {
            volleyGet(param);
        }
*/
    }

    private void volleyJson(final DataParams param, int method) {
        JSONObject jsonObject = new JSONObject();
        try {
            for (Object o : param.getParams().entrySet()) {
                Map.Entry entry = (Map.Entry) o;
                jsonObject.put((String) entry.getKey(), entry.getValue());
            }
            LogUtil.d(TAG, "JSONObject: " + jsonObject);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
                method,
                param.getRequestUrl(),
                jsonObject,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        // response
                        LogUtil.d(TAG, "Response: " + response);
                        disposeResult(param.getApi(), response.toString(), param.isShowLoading());
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // error
                        showToast(R.string.request_failed);
                        disposeResult(param.getApi(), null, param.isShowLoading());
                    }
                });
        VolleyDataUtils.addRequest(jsonObjectRequest);
    }

    private void volleyString(final DataParams param, int method) {
        final String strMethod = param.getApi().getHttpMethod().getMethod();
        StringRequest request = new StringRequest(method,
                param.getRequestUrl(), new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                // response
                LogUtil.d(TAG, "Response: " + response);
                disposeResult(param.getApi(), response, param.isShowLoading());
            }

        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                // error
                showToast(R.string.request_failed);
                disposeResult(param.getApi(), null, param.isShowLoading());
            }

        }) {

            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                LogUtil.d(TAG, strMethod + " request url:" +
                        param.getRequestUrl() + ", params:" + param.getParams().toString()
                        + ", headers: " + toJson(VolleyDataUtils.mHeaders));
                return param.getParams();
            }

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {
                String str = null;
                try {
                    //获取SESSION_ID，保存在本地中
//                    Map<String, String> responseHeaders = response.headers;
//                    String rawCookies = responseHeaders.get("Set-Cookie");
//                    String[] splitCookie = rawCookies.split(";");
//                    if (splitCookie.length > 0) {
//                        String[] splitSessionId = splitCookie[0].split("=");
//                        if (splitSessionId.length > 0) {
//                            PreferencesUtils.putString(Key.SESSION_ID, splitSessionId[1]);
//                            LogUtil.d(TAG, "session:" + splitSessionId[1]);
//                        }
//                    }
                    // Chris, set "UTF-8" format.
                    str = new String(response.data, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return Response.success(str, HttpHeaderParser.parseCacheHeaders(response));
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                return VolleyDataUtils.mHeaders;
            }

        };
        VolleyDataUtils.addRequest(request);
    }

    private void volleyGet(final DataParams param) {
        String url = param.getRequestUrl();
        for (Object o : param.getParams().entrySet()) {
            Map.Entry entry = (Map.Entry) o;
            url = url + "/" + entry.getKey() + "/" + entry.getValue();
        }
        final String strMethod = param.getApi().getHttpMethod().getMethod();
        StringRequest request = new StringRequest(url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        LogUtil.d(TAG, "Response: " + response);
                        disposeResult(param.getApi(), response, param.isShowLoading());
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                showToast(R.string.request_failed);
                disposeResult(param.getApi(), null, param.isShowLoading());
            }
        }) {

            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                LogUtil.d(TAG, strMethod + " request url:" +
                        param.getRequestUrl() + ", params:" + param.getParams().toString()
                        + ", headers: " + toJson(VolleyDataUtils.mHeaders));
                return param.getParams();
            }

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {
                String str = null;
                try {
                    // Chris, set "UTF-8" format.
                    str = new String(response.data, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return Response.success(str, HttpHeaderParser.parseCacheHeaders(response));
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                return VolleyDataUtils.mHeaders;
            }

        };
        VolleyDataUtils.addRequest(request);
    }

    private void disposeResult(Api api, String response, boolean loadHint) {
        if (loadHint)
            dismissProgressDialog();
        if (response == null) {
            errorResponse();
            return;
        }
        try {
            disposeResult(api, response);
        } catch (Exception e) {
            showToast(R.string.process_data_error);
            LogUtil.e(TAG, "Data handler error: " + e.getMessage());
            e.printStackTrace();
        }
    }

    protected void errorResponse() {

    }
}
